package com.tabnet.form.client;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.joda.time.DateTime;

import com.tabnet.beans.personnes.Adresse;
import com.tabnet.beans.personnes.Client;
import com.tabnet.dao.DAOClient;
import com.tabnet.dao.DAOException;
import com.tabnet.form.FormValidationException;

public class CreationClientForm {
    private static final String CHAMP_NOM		= "nomClient";
    private static final String CHAMP_PRENOM	= "prenomClient";
    private static final String CHAMP_NAISSANCE	= "dateClient";
    private static final String CHAMP_TELEPHONE	= "telephoneClient";
    private static final String CHAMP_MAIL		= "emailClient";
    private static final String CHAMP_MDP		= "mdpClient";
    private static final String CHAMP_CONFMDP	= "confClient";
    private static final String CHAMP_RUE		= "adresseRueClient";
    private static final String CHAMP_CP		= "adresseCPClient";
    private static final String CHAMP_VILLE		= "adresseVilleClient";
    private static final String CHAMP_PAYS		= "adressePaysClient";
    

    private String resultat = "";
    private Map<String, String> erreurs = new HashMap<String, String>();
    private DAOClient oClientDao;


    public CreationClientForm( DAOClient pClientDao ) {
        this.oClientDao = pClientDao;
    }

    public Map<String, String> getErreurs() {
        return this.erreurs;
    }
    public String getResultat() {
        return this.resultat;
    }

    /**
     * <p>Fonction creerClient<br />
     * Créer un client à partir des données entrées par l'utilisateur.
     * Si aucune erreur, le client est enregistré dans la base de données
     * sinon l'utilisateur doit corriger les erreurs.</p>
     * @param request : objet HttpServletRequest
     * @return une instance Client
     */
    public Client creerClient( HttpServletRequest request ) {
    	
    	// récupération des valeurs
        String nom = getValeurChamp( request, CHAMP_NOM );
        String prenom = getValeurChamp( request, CHAMP_PRENOM );
        String telephone = getValeurChamp( request, CHAMP_TELEPHONE );
        String naissance = getValeurChamp( request, CHAMP_NAISSANCE );
        
        String rue = getValeurChamp( request, CHAMP_RUE );
        String ville = getValeurChamp( request, CHAMP_VILLE );
        String cp = getValeurChamp( request, CHAMP_CP );
        String pays = getValeurChamp( request, CHAMP_PAYS );
        
        String mail = getValeurChamp( request, CHAMP_MAIL );
        String mdp = getValeurChamp( request, CHAMP_MDP );
        String confMDP = getValeurChamp( request, CHAMP_CONFMDP );

        // création des objets
        Client oClient = new Client();
        Adresse oAdresse = new Adresse();

        // les tests de validation des données
        this.traiterNom(nom, oClient);
        this.traiterPrenom(prenom, oClient);
        this.traiterTelephone(telephone, oClient);
        this.traiterDate(naissance, oClient);
        
        this.traiterRue(rue, oAdresse);
        this.traiterVille(ville, oAdresse);
        this.traiterCP(cp, oAdresse);
        this.traiterPays(pays, oAdresse);
        
        this.traiterMail(mail, oClient);
        this.traiterMdp(mdp, confMDP, oClient);
        
        oClient.setAdresse(oAdresse);

        try {
            if ( this.erreurs.isEmpty() ) {
            	this.oClientDao.addClient( oClient );
                this.resultat = "Succès de la création du client.";
            } else {
                this.resultat = "Échec de la création du client.";
            }
        } catch ( DAOException e ) {
        	this.setErreur( "imprévu", "Erreur imprévue lors de l'insertion dans la base de données." );
            this.resultat = e.getMessage() + "<br /> Échec de la création du client.";
        }

        return oClient;
    }
    
    /**
     * Procédure traiterNom
     * Contrôle le nom du client
     * @param pNom: nom du client
     * @param pClient: objet Client
     * */
    private void traiterNom( String pNom, Client pClient ) {
        try {
            this.validationNom( pNom );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_NOM, e.getMessage() );
        }
        pClient.setNom( pNom );
    }
    
    /**
     * Procédure traiterPrenom
     * Contrôle le prenom du client
     * @param pPrenom: prenom du client
     * @param pClient: objet Client
     * */
    private void traiterPrenom( String pPrenom, Client pClient ) {
        try {
            this.validationPrenom(pPrenom);
        } catch ( Exception e ) {
            this.setErreur( CHAMP_PRENOM, e.getMessage() );
        }
        pClient.setPrenom( pPrenom );
    }
    /**
     * 
     * Procédure traiterTelephone
     * Contrôle le telephone du client
     * @param pTelephone: telephone du client
     * @param pClient: objet Client
     * */
    private void traiterTelephone( String pTelephone, Client pClient ) {
        try {
            this.validationTelephone(pTelephone);
        } catch ( Exception e ) {
            this.setErreur( CHAMP_TELEPHONE, e.getMessage() );
        }
        pClient.setTelephone( pTelephone );
    }
    
    /**
     * Procédure traiterDate
     * Contrôle la date de naissance du client
     * @param pDate: date de naissance du client
     * @param pClient: objet Client
     * */
    private void traiterDate( String pDate, Client pClient ) {
        try {
            this.validationDate(pDate);
        } catch ( Exception e ) {
            this.setErreur( CHAMP_NAISSANCE, e.getMessage() );
        }
        pClient.setNaissance( new DateTime( pDate ));
    }
    
    /**
     * Procédure traiterRue
     * Contrôle la rue du client
     * @param pRue: rue du client
     * @param pAdresse: objet Adresse
     * */
    private void traiterRue( String pRue, Adresse pAdresse ) {
        try {
        	this.validationRue( pRue );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_RUE, e.getMessage() );
        }
        pAdresse.setRue( pRue );
    }
    
    /**
     * Procédure traiterCP
     * Contrôle le code postal du client
     * @param pCP: code postal du client
     * @param pAdresse: objet Adresse
     * */
    private void traiterCP( String pCP, Adresse pAdresse ) {
        try {
        	this.validationCP( pCP );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_CP, e.getMessage() );
        }
        pAdresse.setCodePostal( pCP );
    }
    
    /**
     * Procédure traiterVille
     * Contrôle lav ille du client
     * @param pVille: ville du client
     * @param pAdresse: objet Adresse
     * */
    private void traiterVille( String pVille, Adresse pAdresse ) {
        try {
        	this.validationVille( pVille );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_VILLE, e.getMessage() );
        }
        pAdresse.setVille( pVille );
    }
    
    /**
     * Procédure traiterPays
     * Contrôle le pays du client
     * @param pPays: pays du client
     * @param pAdresse: objet Adresse
     * */
    private void traiterPays( String pPays, Adresse pAdresse ) {
        try {
        	this.validationPays( pPays );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_PAYS, e.getMessage() );
        }
        pAdresse.setPays(pPays);
    }
    
    /**
     * Procédure traiterMail
     * Contrôle le mail du client
     * @param pMail: mail du client
     * @param pClient: objet Client
     * */
    private void traiterMail( String pMail, Client pClient ) {
        try {
            this.validationMail( pMail, pClient.getId());
        } catch ( Exception e ) {
            this.setErreur( CHAMP_MAIL, e.getMessage() );
        }
        pClient.setMail( pMail );
    }
    
    /**
     * Procédure traiterMdp
     * Contrôle le mot de passe du client
     * @param pMDP: mot de passe du client
     * @param pMDPConf: confirmation du mot de passe client
     * @param pClient: objet Client
     * */
    private void traiterMdp( String pMDP, String pMDPConf, Client pClient ) {
        try {
            this.validationMdp( pMDP, pMDPConf );
        } catch ( Exception e ) {
            this.setErreur( CHAMP_MDP, e.getMessage() );
        }
        pClient.setMDP( pMDP );
    }
    
    /**
     * LES VALIDATIONS
     * */
    private void validationNom( String pNom ) throws FormValidationException {
        if ( pNom == null || pNom.length() < 2 )
            throw new FormValidationException( "Le nom doit contenir au moins 2 caractères." );
    }
    
    private void validationPrenom( String pPrenom ) throws FormValidationException {
        if ( pPrenom != null && pPrenom.length() < 2 )
            throw new FormValidationException( "Le prenom doit contenir au moins 2 caractères." );
    }
    
    private void validationTelephone( String pTelephone ) throws FormValidationException {
        if ( pTelephone != null ) {
            if ( !pTelephone.matches( "^0\\d([-.\\s]?\\d{2}){4}$" ) ) //  ^\\d+$
                throw new FormValidationException( "Le numéro de téléphone doit uniquement contenir des chiffres." );
            else if ( pTelephone.length() < 10 )
                throw new FormValidationException( "Le numéro de téléphone doit contenir au moins 10 caractères." );
        }
        else
            throw new FormValidationException( "Merci d'entrer un numéro de téléphone." );
    }
    
    private void validationDate( String pDate ) throws FormValidationException{
    	if ( pDate != null && !pDate.isEmpty()) {
    		DateTime date = new DateTime(pDate);
    		
            if ( date.isAfterNow() )
                throw new FormValidationException( "La date de naissance ne peut être supérieur à la date actuelle." );
            
            if ( date.plusYears(18).isAfterNow()  )
                throw new FormValidationException( "Vous devez avoir 18 ans pour vous inscrire." );
        }
        else
            throw new FormValidationException( "Merci d'entrer une date de naissance." );
    }
    
    private void validationRue( String pRue ) throws FormValidationException {
        if ( pRue != null ) {
            if ( pRue.length() < 5 )
                throw new FormValidationException( "La rue du client doit contenir au moins 5 caractères." );
        }
        else
            throw new FormValidationException( "Merci d'entrer la rue du client." );
    }

    private void validationCP( String pCP ) throws FormValidationException {
        if ( pCP != null ) {
            if ( pCP.length() < 5 )
                throw new FormValidationException( "Le numéro de code postal doit contenir au moins 5 chiffres." );
        }
        else
            throw new FormValidationException( "Merci d'entrer un code postal." );
    }
    
    private void validationVille( String pVille ) throws FormValidationException {
        if ( pVille != null ) {
            if ( pVille.length() < 2 )
                throw new FormValidationException( "La ville du client doit contenir au moins 2 caractères." );
        }
        else
            throw new FormValidationException( "Merci d'entrer la ville du client." );
    }
    
    private void validationPays( String pPays ) throws FormValidationException {
        if ( pPays != null ) {
            if ( pPays.length() < 2 )
                throw new FormValidationException( "Le pays du client doit contenir au moins 2 caractères." );
        }
        else
            throw new FormValidationException( "Merci d'entrer le pays du client." );
    }
    
    private void validationMail( String pMail, int pId ) throws FormValidationException, DAOException {
    	if(!this.oClientDao.checkMail(pMail, pId))
    		throw new FormValidationException( "Adresse mail déjà existante." );
    	else{
	        if ( pMail == null || !pMail.matches( "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) )
	            throw new FormValidationException( "Merci de saisir une adresse mail valide." );
    	}
    }
    
    private void validationMdp( String pMDP, String pConfMDP ) throws FormValidationException {
        if ( pMDP != null ) {
            if ( pMDP.length() < 5 ) {
                throw new FormValidationException( "Le mot de passe du fournisseur doit contenir au moins 5 caractères." );
            }
            else if(!pMDP.equals(pConfMDP))
                throw new FormValidationException( "La confirmation du mot de passe n'est pas identique." );
        }
        else
            throw new FormValidationException( "Merci d'entrer un mot de passe Fournisseur." );
    }

    /*
     * Ajoute un message correspondant au champ spécifié à la map des erreurs.
     */
    private void setErreur( String champ, String message ) {
        this.erreurs.put( champ, message );
    }

    private static String getValeurChamp( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 )
            return null;
        else
            return valeur;
    }
}
